using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using log4net;

namespace Neo.Core.Util
{
    public class DeclarativeEntityMapFactory : EntityMapFactoryBase
    {
        //--------------------------------------------------------------------------------------
		//	Static fields and constructor
		//--------------------------------------------------------------------------------------

		private static DeclarativeEntityMapFactory sharedInstance;
        private List<Type> typeList;


        //--------------------------------------------------------------------------------------
		//	Singleton
		//--------------------------------------------------------------------------------------

		/// <summary>
		/// Gets the shared instance of this class.
		/// </summary>
		/// <remarks>
		/// It is possible to create further instances but unless there is a specific need for
		/// one it is advisable to use the shared one because this avoids the overhead of 
		/// searching through the assemblies multiple times.
		/// </remarks>
		public static DeclarativeEntityMapFactory SharedInstance
		{
			get
			{
				if(sharedInstance == null)
					sharedInstance = new DeclarativeEntityMapFactory();
				return sharedInstance;
			}
		}

        public List<Type> TypeList
        {
            get { return typeList; }
        }


        //--------------------------------------------------------------------------------------
		//	Fields and constructor
		//--------------------------------------------------------------------------------------		

		/// <summary>
		/// Initialises a new instance of this class.
		/// </summary>
		/// <remarks>
		/// Only create new instances if the shared one cannot be used.
		/// </remarks>
        private DeclarativeEntityMapFactory()
		{
			if(logger == null)
				logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString());
            if(typeList == null)
                typeList = new List<Type>();
		}

        protected override void RegisterEntityMaps()
        {
            TypeFilter filter = IsIEntityMap;
            foreach (Type t in typeList)
            {
                if ((t.IsClass) && (t.IsAbstract == false) && (t.FindInterfaces(filter, null).Length > 0) && (registeredTypes.Contains(t) == false))
                {
                    registeredTypes.Add(t);
                    IEntityMap m = (IEntityMap)Activator.CreateInstance(t);
                    m.Factory = this;
                    mapByObjectTypeTable[m.ObjectType] = m;
                    if (mapByTableNameTable.ContainsKey(m.TableName))
                    {
                        logger.Error(m.TableName + " appears twice - unpredictable behaviour");
                    }
                    mapByTableNameTable[m.TableName] = m;
                }
            }
        }
    }
}
